﻿using DataProcess.Enums;
using DevExpress.XtraBars;
using System;
using System.Windows.Forms;
using Newtonsoft.Json;
using DataProcess.DataAccess;
using DevExpress.XtraEditors;
using DataProcess.Tools;
using System.ComponentModel;

namespace DataProcess.Views
{
    public partial class DataDetailsForm<T> : DevExpress.XtraBars.Ribbon.RibbonForm where T : class, new()
    {
        protected virtual DbContext<T> DBContext { get; set; }

        public DataDetailsForm(T item, DataEditType det, int rowHandle = -1)
        {
            DataEditType = det;
            RowHandle = rowHandle;
            DBContextInit();
            InitializeComponent();
            Initialize(item, det, rowHandle);
        }

        /// <summary>
        /// 数据状态
        /// </summary>
        public DataEditType DataEditType { get; private set; }

        /// <summary>
        /// 主面板上数据的RowHandle
        /// </summary>
        public int RowHandle { get; private set; }

        /// <summary>
        /// 用于更新主面板数据的委托
        /// </summary>
        public Action<int, T, DataEditType> UpdateMainRow;

        /// <summary>
        /// 旧数据
        /// </summary>
        public T OldItem { get; private set; }

        /// <summary>
        /// 新数据
        /// </summary>
        public T NewItem { get; private set; }

        protected virtual void DBContextInit()
        {
            DBContext = new DbContext<T>();
        }

        public virtual void Initialize(T item, DataEditType _mos, int rowHandle)
        {
            NewItem = new T();
            if (item == null)
            {
                OldItem = new T();
            }
            else
            {
                OldItem = item;
            }
            var json = JsonConvert.SerializeObject(item);
            OldItem = JsonConvert.DeserializeObject<T>(json);
            NewItem = JsonConvert.DeserializeObject<T>(json);
        }

        protected void DataDetailsForm_Load(object sender, EventArgs e)
        {
            SetDetailsLayout();
#if DEBUG
            DetailsLayout.AllowCustomization = true;
            Layout_RPG.Visible = true;
#else
            DetailsLayout.AllowCustomization = false;
            Layout_RPG.Visible = false;
#endif
        }

        protected virtual void SetDetailsLayout()
        {
            DetailsLayout.DataSource = new BindingList<T>() { NewItem };
            DetailsLayout.RetrieveFields();

            System.Drawing.Size size = DetailsLayout.RestoreLayoutAndSizeFromXml(typeof(T));
            if (size != default)
            {
                Size = size;
            }
        }

        protected void DataDetailsForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }

        protected void Save_BBI_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (OperatorInfoResult($"确定执行该操作么?点击\"确定\"会将数据{(DataEditType == DataEditType.Add ? "新增" : "更新")}至数据库!") != DialogResult.OK)
            {
                return;
            }

            DataSave();
        }

        protected void SaveAndClose_BBI_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (OperatorInfoResult($"确定执行该操作么?点击\"确定\"会将数据{(DataEditType == DataEditType.Add ? "新增" : "更新")}至数据库并关闭该窗体") != DialogResult.OK)
            {
                return;
            }

            DataSave(false);
            DialogResult = DialogResult.OK;
        }

        protected void Reset_BBI_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (OperatorWaringResult("确定执行该操作么?点击\"确定\"将撤销所有更改!", "警告") == DialogResult.OK)
            {
                NewItem = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(OldItem));
                DetailsLayout.DataSource = new BindingList<T>() { NewItem };
            }
        }

        protected void DataSave(bool SavedMsg = true)
        {
            if (!DetailsLayout.Validate()) return;

            switch (DataEditType)
            {
                case DataEditType.Add:
                    DataInsert(SavedMsg);
                    break;
                case DataEditType.Modify:
                    DataUpdate(SavedMsg);
                    break;
            }
        }

        protected void DataInsert(bool SavedMsg = true)
        {
            try
            {
                if (DBContext.CurrentDb.Insert(NewItem))
                {
                    UpdateMainRow?.Invoke(RowHandle, NewItem, DataEditType);
                    if (SavedMsg) OperatorInfoResult("保存成功!");
                }
                else
                {
                    OperatorWaringResult("保存失败");
                }
            }
            catch (Exception ex)
            {
                OperatorErrorResult(ex.Message);
            }
        }

        protected void DataUpdate(bool SavedMsg = true)
        {
            try
            {
                if (DBContext.CurrentDb.Update(NewItem))
                {
                    UpdateMainRow?.Invoke(RowHandle, NewItem, DataEditType);
                    if (SavedMsg) OperatorInfoResult("保存成功!");
                }
                else
                {
                    OperatorWaringResult("保存失败");
                }
            }
            catch (Exception ex)
            {
                OperatorErrorResult(ex.Message);
            }
        }


        protected DialogResult OperatorWaringResult(string test, string caption = "警告")
        {
            return XtraMessageBox.Show(this, test, caption, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
        }

        protected DialogResult OperatorErrorResult(string test, string caption = "错误")
        {
            return XtraMessageBox.Show(this, test, caption, MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
        }

        protected DialogResult OperatorInfoResult(string test, string caption = "提示")
        {
            return XtraMessageBox.Show(this, test, caption, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void Layout_BBI_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (OperatorWaringResult("确定要保存现有布局么?") == DialogResult.OK)
            {
                DetailsLayout.SaveLayoutAndSizeToXml(typeof(T), Size);
            }
        }

        private void DetailsLayout_ItemAdded(object sender, EventArgs e)
        {
            if (sender.GetType() == typeof(DevExpress.XtraLayout.LayoutControlItem))
            {
                ((DevExpress.XtraLayout.LayoutControlItem)sender).DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
            }
        }
    }
}